# -*- coding: utf-8 -*-
# @File  : 进程通信之队列.py
# @Author: zbh
# @Date  : 2025/2/25_15:11


'''
1、使用multiprocessing.joinable_queue()创建一个可连接的队列,它比较标准库中的Queue.Queue()多了一个task_done()方法和一个join()方法。
 而且是多进程安全的，不用担心互斥和死锁的问题。
2、task_done()方法：用于通知队列，任务已经完成。
3、join()方法：用于阻塞当前进程，直到队列中的所有任务都被处理完毕。
'''

# 比如，有一个仓库用来存放商品，假如最多只能放5个商品，A不停的放，B不停的取，A和B的放取速度不一致，就可以用队列来做

import multiprocessing
import time
import queue
import random

def producterA(test_queue): # 生产者A
    product_id = 1
    while True:
        print("A 查看当前队列的长度：",test_queue.qsize())
        test_queue.put(product_id)  # 往队列中放数据
        print(f"A 放入 ：[商品{product_id}，放入后的队列长度是：{test_queue.qsize()}]") # 如果队列已达到最大长度，会阻塞，直到队列中有空闲位置
        product_id += 1 # 商品id+1
        time.sleep(random.randint(1,3))


def customerB(test_queue): # 消费者B
    while True:
        print("B 查看当前队列的长度：",test_queue.qsize())
        print(f"B 取出[{test_queue.get()}],取出后的队列长度是：{test_queue.qsize()}") # 如果队列为空，会阻塞，直到队列中有数据
        time.sleep(random.randint(1,3))


def main():
    test_queue = multiprocessing.JoinableQueue(maxsize=5) # 创建一个可连接的队列，队列的最大长度为5
    p = multiprocessing.Process(target=producterA, args=(test_queue,)) # 创建一个生产者A的进程
    c = multiprocessing.Process(target=customerB, args=(test_queue,)) # 创建一个消费者B的进程
    p.start() # 启动生产者A的进程
    c.start() # 启动消费者B的进程
    p.join() # 等待生产者A的进程结束
    c.join() # 等待消费者B的进程结束


if __name__ == "__main__":
    main()


